package cn.jiangzeyin.job;

import cn.jiangzeyin.entity.CacheJobInfo;
import cn.jiangzeyin.entity.IQuartzInfo;
import cn.jiangzeyin.log.JobLog;
import cn.jiangzeyin.system.JobDataUtil;
import cn.jiangzeyin.system.SystemJobManager;
import org.quartz.JobExecutionContext;

import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 系统守护调度
 *
 * @author jiangzeyin
 */
public class SystemJobListening extends BaseJob {
    private final static ConcurrentHashMap<String, CacheJobInfo> CACHE_JOB_INFO_HASH_MAP = new ConcurrentHashMap<>();
    private static Listening listening;

    /**
     * 添加系统监听事件回调
     *
     * @param listening 监听
     */
    public static void setListening(Listening listening) {
        SystemJobListening.listening = listening;
    }

    @Override
    public void execute(JobExecutionContext context) {
        // TODO Auto-generated method stub
        try {
            super.execute(context);
            // 调度检查
            quartzRun();
            if (listening != null) {
                listening.execute();
            }
        } catch (Exception e) {
            // TODO: handle exception
            JobLog.getInstance().error("系统调度监听异常", e);
        } finally {
            putStatus();
        }
    }

    /**
     * 检查调度信息
     *
     * @author jiangzeyin
     */
    private void quartzRun() {
        List<IQuartzInfo> list = JobDataUtil.getInstance().getAll(SystemJobManager.getDebugInfo());
        if (list == null) {
            return;
        }
        for (IQuartzInfo quartzInfo : list) {
            if (quartzInfo == null) {
                continue;
            }
            try {
                // 判断是否存在
                String key = JobUtil.getJobKeyName(quartzInfo);
                if (!CACHE_JOB_INFO_HASH_MAP.containsKey(key)) {
                    // 调试模式直接开启
                    if (SystemJobManager.isDebug()) {
                        JobUtil.addQuartz(quartzInfo);
                        continue;
                    }
                    // 新建任务
                    if (quartzInfo.isActive() && quartzInfo.getStatus() == IQuartzInfo.Status.Run.getCode()) {
                        JobUtil.addQuartz(quartzInfo);
                        continue;
                    }
                }
                // 调试模式不进行数据和状态检查
                if (SystemJobManager.isDebug()) {
                    continue;
                }
                CacheJobInfo job = CACHE_JOB_INFO_HASH_MAP.get(key);
                if (job == null) {
                    continue;
                }
                // 判断是否删除
                if (quartzInfo.isDelete()) {
                    JobUtil.deleteJob(job.getJob().getKey(), job.getTrigger().getKey());
                    CACHE_JOB_INFO_HASH_MAP.remove(key);
                    continue;
                }
                // 暂停
                if (quartzInfo.getStatus() == IQuartzInfo.Status.Stop.getCode()) {
                    // 判断是否已经暂停
                    if (job.getStatus() != quartzInfo.getStatus()) {
                        JobUtil.pauseJob(job.getJob().getKey(), job.getTrigger().getKey());
                        job.setStatus(IQuartzInfo.Status.Stop.getCode());
                    }
                    continue;
                }
                // 判断任务信息是否变化
                if (quartzInfo.getStatus() == IQuartzInfo.Status.Run.getCode()) {
                    // 运行类
                    if (!quartzInfo.getRunClass().equalsIgnoreCase(job.getRunClass())) {
                        JobUtil.deleteJob(job.getJob().getKey(), job.getTrigger().getKey());
                        CACHE_JOB_INFO_HASH_MAP.remove(key);
                        JobUtil.addQuartz(quartzInfo);
                        continue;
                    }
                    // 时间变化
                    if (!quartzInfo.getCron().equalsIgnoreCase(job.getCron())) {
                        JobUtil.deleteJob(job.getJob().getKey(), job.getTrigger().getKey());
                        CACHE_JOB_INFO_HASH_MAP.remove(key);
                        JobUtil.addQuartz(quartzInfo);
                        continue;
                    }
                    // 恢复任务
                    if (job.getStatus() == IQuartzInfo.Status.Stop.getCode()) {
                        JobUtil.resumeJob(job.getJob().getKey(), job.getTrigger().getKey());
                        job.setStatus(IQuartzInfo.Status.Run.getCode());
                        continue;
                    }
                }
                // 调度异常状态暂停运行
                if (quartzInfo.getStatus() == IQuartzInfo.Status.Error.getCode()) {
                    JobUtil.pauseJob(job.getJob().getKey(), job.getTrigger().getKey());
                    job.setStatus(IQuartzInfo.Status.Error.getCode());
                }
            } catch (Exception e) {
                // TODO: handle exception
                JobLog.getInstance().error("处理调度异常" + quartzInfo.getName(), e);
            }
        }
    }

    /**
     * 添加调度信息
     *
     * @param info info
     * @author jiangzeyin
     */
    static void putRunJobInfo(CacheJobInfo info) {
        CACHE_JOB_INFO_HASH_MAP.put(info.getKey(), info);
    }

    static boolean containsQuartzInfo(String key) {
        return CACHE_JOB_INFO_HASH_MAP.containsKey(key);
    }

    /**
     * 获取运行的调度信息
     *
     * @param key key
     * @return 对象
     * @author jiangzeyin
     */
    public static CacheJobInfo getRunJobInfo(String key) {
        return CACHE_JOB_INFO_HASH_MAP.get(key);
    }


    /**
     * 判断是否在运行
     *
     * @param key key
     * @return true 运行
     */
    public static boolean isRun(String key) {
        // 调试模式全运行
        if (SystemJobManager.isDebug()) {
            return true;
        }
        for (CacheJobInfo jobInfo : CACHE_JOB_INFO_HASH_MAP.values()) {
            if (jobInfo.getKey().equals(key)) {
                return jobInfo.getStatus() == IQuartzInfo.Status.Run.getCode();
            }
        }
        return false;
    }

    /**
     * 获取在运行的调度数据
     *
     * @return count
     * @author jiangzeyin
     */
    public static int getRunCount() {
        int i = 0;
        for (CacheJobInfo value : CACHE_JOB_INFO_HASH_MAP.values()) {
            if (value.getStatus() == 0) {
                i++;
            }
        }
        return i;
    }

    /**
     * 获取没有运行的调度，但是在程序缓存中的调度数
     *
     * @return int
     * @author jiangzeyin
     */
    public static int getNotRunCount() {
        int i = 0;
        for (CacheJobInfo value : CACHE_JOB_INFO_HASH_MAP.values()) {
            if (value.getStatus() == 1) {
                i++;
            }
        }
        return i;
    }

    /**
     * 监听
     */
    public interface Listening {
        /**
         * 执行
         */
        void execute();
    }
}
